// 138k 按下为低电平
module btn_trig #(
    parameter integer N_DELAY = 10
) (
    input  sys_clk,
    input  rst_n,
    input  btn_i,
    input  tbase_pulse_i,
    output btn_revent_o,
    output btn_fevent_o
);

  localparam integer StateHigh = 2'b00;
  localparam integer StateWaitLow = 2'b01;
  localparam integer StateLow = 2'b11;
  localparam integer StateWaitHigh = 2'b10;

  localparam integer CntWidth = $clog2(N_DELAY);

  reg [1:0] trig_state;
  reg [1:0] trig_state_next;

  reg btn_sync0, btn_sync1;
  reg  [CntWidth-1:0] delay_cnt;

  wire                delay_timeout;

  // sync input signal
  always @(posedge sys_clk, negedge rst_n) begin
    if (~rst_n) begin
      btn_sync0 <= 1'b1;
      btn_sync1 <= 1'b1;
    end else begin
      {btn_sync1, btn_sync0} <= {btn_sync0, btn_i};
    end
  end

  assign delay_timeout = tbase_pulse_i && (delay_cnt == N_DELAY - 1);

  // delay cnt
  always @(posedge sys_clk, negedge rst_n) begin
    if (~rst_n) begin
      delay_cnt <= 0;
    end else if (trig_state == StateWaitLow || trig_state == StateWaitHigh) begin
      if (tbase_pulse_i) begin
        if (delay_timeout) begin
          delay_cnt <= 0;
        end else begin
          delay_cnt <= delay_cnt + 1'b1;
        end
      end
    end else begin
      delay_cnt <= 0;
    end
  end

  always @(*) begin
    case (trig_state)
      StateHigh: begin
        if (~btn_sync1) begin
          trig_state_next = StateWaitLow;
        end else begin
          trig_state_next = StateHigh;
        end
      end
      StateWaitLow: begin
        if (delay_timeout) begin
          if (~btn_sync1) begin
            trig_state_next = StateLow;
          end else begin
            trig_state_next = StateHigh;
          end
        end else begin
          trig_state_next = StateWaitLow;
        end
      end
      StateLow: begin
        if (btn_sync1) begin
          trig_state_next = StateWaitHigh;
        end else begin
          trig_state_next = StateLow;
        end
      end
      StateWaitHigh: begin
        if (delay_timeout) begin
          if (btn_sync1) begin
            trig_state_next = StateHigh;
          end else begin
            trig_state_next = StateLow;
          end
        end else begin
          trig_state_next = StateWaitHigh;
        end
      end
      default: begin
        trig_state_next = StateHigh;
      end
    endcase
  end

  always @(posedge sys_clk, negedge rst_n) begin
    if (~rst_n) begin
      trig_state <= StateHigh;
    end else begin
      trig_state <= trig_state_next;
    end
  end

  assign btn_fevent_o = (trig_state == StateWaitLow) & (delay_timeout & ~btn_sync1);
  assign btn_revent_o = (trig_state == StateWaitHigh) & (delay_timeout & btn_sync1);

endmodule
